///
/// $Id: timer.cpp,v 1.4 2005/10/16 08:35:49 olegus Exp $
///

#include "timer.h"
#include "time.h"
#include "containers.h"

//////////////////////////////////////////////////////////////////////////

Timer_c::Timer_c()
:   m_ulTicks( 0 )
{
}

void Timer_c::Begin()
{
    m_ulTicks = (unsigned long) clock();
}

double Timer_c::End()
{
    return double(clock() - m_ulTicks) / double(CLOCKS_PER_SEC);
}

//////////////////////////////////////////////////////////////////////////

WatchDog_c::WatchDog_c( double fPeriod )
:   m_fPeriod( fPeriod )
,   m_fTime( 0.0 )
{
    m_cTimer.Begin();
}

bool WatchDog_c::Alarm()
{
    m_fTime += m_cTimer.End();
    m_cTimer.Begin();
    if( m_fTime >= m_fPeriod )
    {
        m_fTime = 0.0;
        return true;
    }
    return false;
}

//////////////////////////////////////////////////////////////////////////

typedef DynamicArray_T< Stats_c * > Statistics_t;
Statistics_t *g_pdStatistics;

Stats_c::Stats_c( const char * szName )
{
    strcpy( m_sName, szName );
    if( g_pdStatistics == NULL )
        g_pdStatistics = new Statistics_t;
    g_pdStatistics->Add( this );
    Reset();
}

Stats_c::~Stats_c()
{
    SafeDelete( g_pdStatistics );
}

void Stats_c::Reset()
{
    m_fAvg      = 0.0;
    m_fMin      = FLT_MAX;
    m_fMax      = 0.0;
    m_fTotal    = 0.0;
    m_fMeasures = 0.0;
}

void Stats_c::Measure( double fValue )
{
    m_fMeasures += 1.0;
    m_fTotal    += fValue;
    m_fMin      = min( m_fMin, fValue );
    m_fMax      = max( m_fMax, fValue );
    m_fAvg      = m_fTotal / m_fMeasures;
}

void Stats_c::Report( Log_c & cLog )
{
    static int iLongestName = 0;
    if( iLongestName == 0 )
    {
        ARRAY_FOREACH( i, (*g_pdStatistics) )
            iLongestName = max( iLongestName, (int)strlen( (*g_pdStatistics)[i]->m_sName ) );
    }
    cLog.Out( "Profiler %-*s: total % e, min % e, max % e, avg % e, measures %.0f\n"
        , iLongestName, m_sName, m_fTotal, m_fMin, m_fMax, m_fAvg, m_fMeasures );
    cLog.Flush();
}

void Stats_c::ResetAll()
{
    ARRAY_FOREACH( i, (*g_pdStatistics) )
        (*g_pdStatistics)[i]->Reset();
}

void Stats_c::ReportAll( Log_c & cLog )
{
    ARRAY_FOREACH( i, (*g_pdStatistics) )
        (*g_pdStatistics)[i]->Report( cLog );
}

//////////////////////////////////////////////////////////////////////////

Profiler_c::Profiler_c( const char * szName )
:   Stats_c( szName )
{
}

void Profiler_c::Begin()
{
    m_cTimer.Begin();
}

void Profiler_c::End()
{
    Measure( m_cTimer.End() );
}

///
/// $Id: timer.cpp,v 1.4 2005/10/16 08:35:49 olegus Exp $
///
